简介
WebPack是一款加载器兼容打包工具。
可以处理各种资源:JS(JSX),coffee,less/sass,图片等。
静态资源打包工具
出色的前端自动化构件化工具,模块化工具,资源管理工具
兼容多种JavaScript书写规范,具有更强大的JavaScript模块化功能
特点
- 使用commonJs的形式书写脚本。也对AMD,CMD的写法支持。
- 所有的静态资源都可以是模块引用,而不仅仅是JavaScript文件了。
- 便捷开发,能够替代部分的grunt/gulp的工作。
- 扩展性强,插件机制完善。
- 仅需要对应的加载器即可支持,配置简单,关注文件依赖关系
工作原理:
把项目当作一个整体,通过一个给定的主文件(如:app.js),webpack将从这个文件开始找到项目中的所有依赖文件,通过loaders处理它们,打包为一个浏览器可以识别的JavaScript文件。
webpack 核心概念
entry
:一个可执行模块或库的入口文件。chunk
:多个文件组成的一个代码开,例如把一个可执行模块和它所有依赖的模块组合和一个chunk
。loader
:文件转换器。plugin
:插件,用于扩展webpack
的功能,在webpack
构建生命周期的节点上加入扩展hook
为webpack
加入功能。
webpack构建流程
从启动webpack构建到输入结果经历了一系列过程:
- 解析
webpack
配置参数,合并从shell
传入webpack.config.js
文件里配置的参数,生产最后的配置结果 - 注册所有配置的插件,好让插件监听
webpack
构建生命周期的事件节点,以做出对应的反应 - 从配置的
entry
文件入口开始解析文件构建AST
语法树,找出每个文件所依赖的文件,递归下去。 - 在解析文件递归的过程中根据文件类型和
loader
配置找出合适的loader
用来对文件进行转换 - 递归完后得到每个文件的最后总结果,根据
entry
配置生成代码块chunk
- 输出所有
chunk
到文件系统
注意,在构建生命周期中有一系列插件在合适的时机做了合适的事情,比如UglifyJsPlugin
会在loader
转换递归完后对结果再使用UglifyJs
压缩覆盖之前的结果。
webpack配置文件
webpack.config.js
配置说明:
- plugins 插件项
- entry 页面入口文件
- output 对应输出项(即入口文件最终生成位置,名字)
- modules.loaders 配置每一个种资源文件需要使用什么加载器来处理(多个loader之间使用"!" 连接)
基本命令
webpack
启动webpack的方法webpack -p
发布环境编译(压缩代码),对打包后的文件进行压缩webpack -w
提供watch方法,实时进行进行打包更新webpack -d
提供source map,方便调试webpack --config xx.js
以某个config作为打包,使用另外一份配置文件来打包(例如:webpack.config2.js)webpack --help
更多的命令
使用&配置
Node API 使用:
var webpack = require('webpack');
默认使用当前目录的webpack.config.js 作为配置文件。可以根据不同的需求配置不同的config
极简webpack配置文件
moudle.exports = {
entry: [
'./app/main.js'
],
output: {
path: __dirname + '/dist/',
publicPath: '/dist/',
filename: 'bundle.js'
}
}
其中entry参数定义了打包后的入口文件,数组中的所有文件会打包生成一个filename文件
output参数定义了输出文件的位置
在 package.json
文件中配置
"scripts": {
"dev": "webpack",
"deploy": "webpack --config webpack.deploy.config.js",
"test": "echo \"Error: no test specified\" && exit 1"
}
可以使用 npm run dev
和 npm run deploy
指令.
需要在package.json
文件所在目录指令有效
复杂的配置
公共文件提取
使用了一个 CommonsChunkPlugin 的插件,它用于提取多个入口文件的公共脚本部分,然后生成一个common.js 来方便多页面之间进行复用
var CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
module.exports = {
entry: {a: './a', b: './b'},
output: { filename: '[name].js' },
plugins: [ new CommonsChunkPlugin('common.js') ]
}
<script src="common.js"></script>
<script src="a.js"></script>
<script src="b.js"></script>
有用的配置项
module.noParse
如果确定一个模块中没有其它依赖的,就可以配置这项,webpack将不再扫描这个文件中的依赖
module: {
loaders: [{ test: /\.css$/, loader: 'style-loader'}],
noParse: [/moment-with-locales/]
}
resolve.alias
别名.是Webpack 的一个配置项,它的作用是把用户的一个请求重定向到另一个路径 (理解成 302)
resolve: {
extensions: ['.js', '.less', '.css'],
alias: {
moment: "moment/min/moment-with-locales.min.js"
}
}
加载器
对应各种不同的资源,需要有各自的loader
模块: 静态的文件, 比如: JavaScript,CSS, LESS, TypeScript
JSX,CoffeeScript,图片等等
文件配置: 通过正则表达式对文件名进行匹配.
对于不同的模块有其对应的模块加载器,它们可以进行串联
module: {
loaders: [{
test: /\.less$/,
loader: 'style=loader!css-loader!less-loader'
}, {
test: /\.(png!jpe?g)$/,
loader: 'url-loader?limit=10000&name=build/[name].[ext]'
}]
}
require() 还支持在资源path前面指定loader,即 require(![loaderslist]![source path]) 形式
require("style!css!less!./mystyles.less");
不同规范的模块加载实现 ( AMD、CommonJS、ES6 )
CommonJS 的rqeuire函数则是同步加载 -- 使用require.ensure实现兼容
AMD是模块异步加载并保证执行顺序 -- 使用require实现兼容
ES6中使用import实现模块的引入 -- 使用Babel实现兼容
在Webpack中推荐CommonJS方法去加载模块,这种方式语法更加简洁直观.
webpack 内部实现命令不同
require.ensure(CommonJs); // 保证CommonJs顺序
require.ensure(['module-a', 'module-b'], function ( require ) {
var a = require('module-a');
var b = require('module-b');
// ...
});
require(AMD);
require(['module-a', 'module-b'], function ( a, b ) {
// ...
});
require.include(request);
require.ensure([], function( require ) {
require.include('./file');
require('./file2');
});
sourcemap
可以把开发文件在浏览器中显示,便于调试
module.exports = {
entry: './entry.js',
output: {
path: __dirname,
filename: 'bundle.js'
},
devtool: 'source-map'
}
webpack-dev-server
生成一个开发使用的服务器,在文件有变化的时候,自动打包。有文件的热替换的功能
webpack-dev-server --inline --hot // 文件自动打包, 模块热替换
react 项目基础搭建
需要的工具
npm install babel-core babel-preset-es2015 babel-parset-react webpack webpack-dev-server babel-loader react-hot-loader --save-dev
npm install react react-dom --save-dev
单独使用babel,需要安装的工具
npm install babel-loader babel-core babel-preset-es2015 --save-dev
模块的引用
使用 require 方式直接引用静态文件
CSS 被转化为style标签
require('./myapp.less');
var myapp = require('./myapp.js');
console.log(myapp);
图片打包
使用rquire方式直接引用静态文件
url-loader可以帮助实现图片的封装打包,也可以通过require实现
图片可能被转化成 base64格式的dataUrl
div.img {
background: url('../img/xxx.jpg');
}
// 或者
var img = document.createElement('img');
img.src = require('../image/xxx.jpg');
document.body.appendChild(img);
CSS文件独立打包
通常并不想把样式打在脚本中,最好独立生成CSS文件,在页面中外链才好,这时可以使用插件extract-text-webpack-plugin --save-dev
npm install extract-text-webpack-plugin --save-dev
plugins: [
new ExtractTextPlugin('styles.css')
]
webapck-dev-server
webpack-dev-server 开发服务器
利用Express开发静态,时时刷新.
基于Node Express框架的轻量级开发服务器
静态资源Web服务器
开发中会监听文件的变化实时打包对于简单静态页面或者仅仅依赖于独立服务的前端页面,都可以直接使用这个开发服务器进行开发
Webpack开发服务器需要单独安装
npm install -g webpack-dev-server
启动命令
webpack-dev-server --content-base build/ --hot
插件
npm install html-webpack-plugin --save-dev
new HtmlWebpackPlugin(),
new HtmlWebpackPlugin({
template: 'app/custom.html',
filename: 'custom.html',
chunks: ['mobile'],
inject: 'body'
})
config
module.exports = {
devtool: "source-map",
entry: getEntry(), //获取项目入口js文件
output: {
path: path.join(__dirname, "dist/js/"), //文件输出目录
publicPath: "dist/js/", //用于配置文件发布路径,如CDN或本地服务器
filename: "[name].js", //根据入口文件输出的对应多个文件名
},
module: {
//各种加载器
loaders: [{
test: /\.css/,
loader: 'style!css'
}, {
test: /\.(png!jpe?g)$/,
loader: 'url-loader?limit=10240&name=build/[name].[ext]'
}, {
test: /\.jsx?$/,
loader: 'babel-loader'
}]
},
resolve: {
//配置别名,在项目中可缩减引用路径
alias: {
jquery: srcDir + "/js/lib/jquery.min.js",
core: srcDir + "/js/core",
ui: srcDir + "/js/ui"
}
},
plugins: [
//提供全局的变量,在模块中使用无需用require引入
new webpack.ProvidePlugin({
jQuery: "jquery",
$: "jquery",
// nie: "nie"
}),
//将公共代码抽离出来合并为一个文件
new CommonsChunkPlugin('common.js'),
//js文件的压缩
new uglifyJsPlugin({
compress: {
warnings: false
}
})
]
};
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。